﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;

namespace Serviio.API
{
    public class ServiioRepository
    {
        private const string endpoint = "/rest/repository";
        private ServiioConnection conn = null;
        
        public bool SearchHiddenFiles { get; set; }
        public bool SearchForUpdates { get; set; }
        public bool AutomaticLibraryUpdate { get; set; }
        public int AutomaticLibraryUpdateInterval { get; set; }

        public int MaxNumberOfItemsForOnlineFeeds { get; set; }
        public int OnlineFeedExpiryInterval { get; set; }
        public string OnlineContentPreferredQuality { get; set; }

        private List<ServiioSharedFolder> sharedFolders = new List<ServiioSharedFolder>();
        public List<ServiioSharedFolder> SharedFolders
        {
            get
            {
                return sharedFolders;
            }
        }

        private List<ServiioOnlineRepository> onlineRepositories = new List<ServiioOnlineRepository>();
        public List<ServiioOnlineRepository> OnlineRepositories
        {
            get
            {
                return onlineRepositories;
            }
        }


        internal ServiioRepository(ServiioConnection connection)
        {
            this.conn = connection;
            Refresh();
        }

        public bool Refresh()
        {
            try
            {
                XmlDocument xDoc = RESTHelper.Get(conn.Host + endpoint);

                SearchHiddenFiles = bool.Parse(xDoc.SelectSingleNode("/repository/searchHiddenFiles").InnerText);
                SearchForUpdates = bool.Parse(xDoc.SelectSingleNode("/repository/searchForUpdates").InnerText);
                AutomaticLibraryUpdate = bool.Parse(xDoc.SelectSingleNode("/repository/automaticLibraryUpdate").InnerText);
                AutomaticLibraryUpdateInterval = int.Parse(xDoc.SelectSingleNode("/repository/automaticLibraryUpdateInterval").InnerText);
                
                SharedFolders.Clear();

                XmlNodeList folderList = xDoc.SelectNodes("/repository/sharedFolders/sharedFolder");
                foreach (XmlNode folderNode in folderList)
                {
                    string id = folderNode.SelectSingleNode("id").InnerText;
                    string path = folderNode.SelectSingleNode("folderPath").InnerText;
                    bool metadata = bool.Parse(folderNode.SelectSingleNode("descriptiveMetadataSupported").InnerText);
                    bool updates = bool.Parse(folderNode.SelectSingleNode("scanForUpdates").InnerText);

                    bool shareVideo = false, shareAudio = false, shareImage = false;

                    XmlNodeList typeList = folderNode.SelectNodes("supportedFileTypes/fileType");
                    foreach (XmlNode typeNode in typeList)
                    {
                        if ("VIDEO".Equals(typeNode.InnerText))
                            shareVideo = true;
                        if ("AUDIO".Equals(typeNode.InnerText))
                            shareAudio = true;
                        if ("IMAGE".Equals(typeNode.InnerText))
                            shareImage = true;
                    }
                    SharedFolders.Add(new ServiioSharedFolder(id, path, shareAudio, shareImage, shareVideo, metadata, updates));
                }

                if (conn.CheckMinVersion("0.6"))
                {
                    MaxNumberOfItemsForOnlineFeeds = int.Parse(xDoc.SelectSingleNode("/repository/maxNumberOfItemsForOnlineFeeds").InnerText);
                    OnlineFeedExpiryInterval = int.Parse(xDoc.SelectSingleNode("/repository/onlineFeedExpiryInterval").InnerText);
                    OnlineContentPreferredQuality = xDoc.SelectSingleNode("/repository/onlineContentPreferredQuality").InnerText;

                    OnlineRepositories.Clear();

                    XmlNodeList sourceList = xDoc.SelectNodes("/repository/onlineRepositories/onlineRepository");
                    foreach (XmlNode sourceNode in sourceList)
                    {
                        string id = sourceNode.SelectSingleNode("id").InnerText;
                        string repositoryName = null;
                        try
                        {
                            repositoryName = sourceNode.SelectSingleNode("repositoryName").InnerText;
                        }
                        catch { }
                        string repositoryType = sourceNode.SelectSingleNode("repositoryType").InnerText;
                        string contentUrl = sourceNode.SelectSingleNode("contentUrl").InnerText;
                        string fileTypeString = sourceNode.SelectSingleNode("fileType").InnerText;
                        string thumbnailUrl = null;
                        try
                        {
                            thumbnailUrl = sourceNode.SelectSingleNode("thumbnailUrl").InnerText;
                        }
                        catch { }
                        bool enabled = true;
                        try
                        {
                            enabled = bool.Parse(sourceNode.SelectSingleNode("enabled").InnerText);
                        }
                        catch { }

                        ServiioOnlineRepository.FileTypes fileType = ServiioOnlineRepository.FileTypes.Unknown;
                        if ("VIDEO".Equals(fileTypeString))
                            fileType = ServiioOnlineRepository.FileTypes.Video;
                        if ("AUDIO".Equals(fileTypeString))
                            fileType = ServiioOnlineRepository.FileTypes.Audio;
                        if ("IMAGE".Equals(fileTypeString))
                            fileType = ServiioOnlineRepository.FileTypes.Image;
                        OnlineRepositories.Add(new ServiioOnlineRepository(id, repositoryName, repositoryType, contentUrl, fileType, thumbnailUrl, enabled));
                    }
                }
            }
            catch
            {
                return false;
            }

            return true;
        }

        public bool Update()
        {
            try
            {
                XmlDocument xDoc = new XmlDocument();
                XmlDeclaration dec = xDoc.CreateXmlDeclaration("1.0", null, null);
                xDoc.AppendChild(dec);
                XmlElement root = xDoc.CreateElement("repository");
                xDoc.AppendChild(root);

                XmlElement xFolders = xDoc.CreateElement("sharedFolders");
                root.AppendChild(xFolders);

                foreach (ServiioSharedFolder folder in SharedFolders)
                {
                    XmlElement xFolder = xDoc.CreateElement("sharedFolder");
                    xFolders.AppendChild(xFolder);

                    if (folder.Id != null)
                    {
                        XmlElement xId = xDoc.CreateElement("id");
                        xId.InnerText = folder.Id;
                        xFolder.AppendChild(xId);
                    }

                    XmlElement xFolderPath = xDoc.CreateElement("folderPath");
                    xFolderPath.InnerText = folder.FolderPath;
                    xFolder.AppendChild(xFolderPath);

                    XmlElement xFileTypes = xDoc.CreateElement("supportedFileTypes");
                    xFolder.AppendChild(xFileTypes);

                    if (folder.ShareAudio)
                    {
                        XmlElement xFileType = xDoc.CreateElement("fileType");
                        xFileType.InnerText = "AUDIO";
                        xFileTypes.AppendChild(xFileType);
                    }
                    if (folder.ShareImages)
                    {
                        XmlElement xFileType = xDoc.CreateElement("fileType");
                        xFileType.InnerText = "IMAGE";
                        xFileTypes.AppendChild(xFileType);
                    }
                    if (folder.ShareVideo)
                    {
                        XmlElement xFileType = xDoc.CreateElement("fileType");
                        xFileType.InnerText = "VIDEO";
                        xFileTypes.AppendChild(xFileType);
                    }

                    XmlElement xMetadata = xDoc.CreateElement("descriptiveMetadataSupported");
                    xMetadata.InnerText = folder.DescriptiveMetadataSupported.ToString();
                    xFolder.AppendChild(xMetadata);

                    XmlElement xScan = xDoc.CreateElement("scanForUpdates");
                    xScan.InnerText = folder.ScanForUpdates.ToString();
                    xFolder.AppendChild(xScan);
                }

                XmlElement xHidden = xDoc.CreateElement("searchHiddenFiles");
                xHidden.InnerText = SearchHiddenFiles.ToString();
                root.AppendChild(xHidden);

                XmlElement xUpdates = xDoc.CreateElement("searchForUpdates");
                xUpdates.InnerText = SearchForUpdates.ToString();
                root.AppendChild(xUpdates);

                XmlElement xAutoUpdate = xDoc.CreateElement("automaticLibraryUpdate");
                xAutoUpdate.InnerText = AutomaticLibraryUpdate.ToString();
                root.AppendChild(xAutoUpdate);

                XmlElement xUpdateInterval = xDoc.CreateElement("automaticLibraryUpdateInterval");
                xUpdateInterval.InnerText = AutomaticLibraryUpdateInterval.ToString();
                root.AppendChild(xUpdateInterval);

                if (conn.CheckMinVersion("0.6"))
                {
                    XmlElement xRepositories = xDoc.CreateElement("onlineRepositories");
                    root.AppendChild(xRepositories);

                    foreach (ServiioOnlineRepository repository in OnlineRepositories)
                    {
                        XmlElement xRepository = xDoc.CreateElement("onlineRepository");
                        xRepositories.AppendChild(xRepository);

                        if (repository.Id != null)
                        {
                            XmlElement xId = xDoc.CreateElement("id");
                            xId.InnerText = repository.Id;
                            xRepository.AppendChild(xId);
                        }

                        XmlElement xRepositoryType = xDoc.CreateElement("repositoryType");
                        xRepositoryType.InnerText = repository.RepositoryType;
                        xRepository.AppendChild(xRepositoryType);

                        XmlElement xContentUrl = xDoc.CreateElement("contentUrl");
                        xContentUrl.InnerText = repository.ContentURL;
                        xRepository.AppendChild(xContentUrl);

                        XmlElement xFileType = xDoc.CreateElement("fileType");
                        xFileType.InnerText = repository.FileTypeString;
                        xRepository.AppendChild(xFileType);

                        XmlElement xThumbnailUrl = xDoc.CreateElement("thumbnailUrl");
                        if (!string.IsNullOrEmpty(repository.ThumbnailURL))
                            xThumbnailUrl.InnerText = repository.ThumbnailURL;
                        xRepository.AppendChild(xThumbnailUrl);

                        if (conn.CheckMinVersion("0.6.1"))
                        {
                            XmlElement xRepositoryName = xDoc.CreateElement("repositoryName");
                            if (!string.IsNullOrEmpty(repository.RepositoryName))
                                xRepositoryName.InnerText = repository.RepositoryName;
                            xRepository.AppendChild(xRepositoryName);

                            XmlElement xEnabled = xDoc.CreateElement("enabled");
                            xEnabled.InnerText = repository.Enabled.ToString();
                            xRepository.AppendChild(xEnabled);
                        }
                    }

                    XmlElement xMaxNumberOfItemsForOnlineFeeds = xDoc.CreateElement("maxNumberOfItemsForOnlineFeeds");
                    xMaxNumberOfItemsForOnlineFeeds.InnerText = MaxNumberOfItemsForOnlineFeeds.ToString();
                    root.AppendChild(xMaxNumberOfItemsForOnlineFeeds);

                    XmlElement xOnlineFeedExpiryInterval = xDoc.CreateElement("onlineFeedExpiryInterval");
                    xOnlineFeedExpiryInterval.InnerText = OnlineFeedExpiryInterval.ToString();
                    root.AppendChild(xOnlineFeedExpiryInterval);

                    XmlElement xOnlineContentPreferredQuality = xDoc.CreateElement("onlineContentPreferredQuality");
                    xOnlineContentPreferredQuality.InnerText = OnlineContentPreferredQuality;
                    root.AppendChild(xOnlineContentPreferredQuality);
                }

                return RESTHelper.Put(conn.Host + endpoint, xDoc);
            }
            catch
            {
                return false;
            }
        }
    }
}
